home *** CD-ROM | disk | FTP | other *** search
- NAME ccsrcv
- ; File CCSRCV.ASM
-
- ;CHINESE
- ifdef MSDOS
- include mssrcv.dat
- else
- include ccsrcv.dat
- endif
-
- code segment public 'code'
- extrn gofil:near, outbuf:near, comnd:near
- extrn spack:near, rpack:near, serini:near, serrst:near
- extrn spar:near, rpar:near, init:near, cxmsg:near, perpos:near
- extrn error:near, error1:near, ptchr:near, erpos:near, rtpos:near
- extrn stpos:near, rprpos:near, nppos:near, nout:near
- extrn dodec:near, doenc:near, errpack:near, intmsg:near
- extrn send11:near, clrmod:near, ihostr:near
- extrn begtim:near, endtim:near, pktsize:near,strlen:near,strcpy:near
- assume cs:code, ds:datas
-
- ; Update retry count and fall through to send a NAK
-
- NAK0: call updrtr ; Update retry count
- nak1: cmp flags.cxzflg,'E' ; Protocol abort sign?
- jne nak2 ; ne = no
- ret ; return to do current ('A') state
- nak2: cmp flags.cxzflg,'C' ; Control-C abort?
- jne nak ; ne = no
- mov pack.state,'A' ; set Abort state
- ret
-
- NAK: mov ax,pack.pktnum ; Get the packet number we're waiting for
- mov pack.seqnum,ax
- mov pack.datlen,0 ; no data
- add fsta.nakscnt,1 ; count NAKs sent
- mov ah,'N' ; NAK that packet
- call spack
- jmp abort ; failed
- nop
- ret
-
- updrtr: cmp pack.state,'A' ; Supposed to abort?
- je upd0 ; Yes, don't bother with retry count
- inc pack.numrtr ; Increment the number of retries
- cmp flags.xflg,1 ; Writing to screen?
- je upd0 ; e = yes, skip this
- cmp pack.numrtr,0 ; non-zero item to display?
- je upd0 ; nothing to display
- push ax ; save packet type in ah
- call rtpos ; Position cursor
- mov ax,pack.numrtr
- call nout ; Write the number of retries
- pop ax ; recover packet type in ah
- upd0: ret
-
- ; Abort
- ABORT PROC NEAR
- cmp filopn,0 ; Disk file open?
- je abort0 ; e = no so don't close
- cmp flags.xflg,1 ; Writing to the screen?
- je abort0 ; Yes, don't close "file"
- call outbuf ; flush last buffer to disk, ignore errors
- nop
- nop
- nop
- mov ah,close2 ; DOS 2.0 file close
- push bx
- mov bx,diskio.handle ; file handle
- int dos
- pop bx
- mov filopn,0 ; say file is no longer open
- cmp flags.abfflg,0 ; save file after closing?
- je abort0 ; e = yes
- push dx
- mov dx,offset diskio.string ; get back file name
- mov ah,del2 ; delete the file
- int dos
- pop dx
- abort0: mov pack.state,'A' ; Otherwise abort
- mov byte ptr locfil,0 ; clear local filename
- or errlev,2 ; set DOS error level
- or fsta.xstatus,2 ; set status
- mov kstatus,2 ; global status
- xor ax,ax ; tell statistics this is a receive operation
- call endtim ; stop file timer
- ret
- ABORT ENDP
-
- ackpak proc near ; send an ACK packet
- mov ah,'Y' ; ack packet
- call spack
- jmp abort ; failed
- nop
- ret
- ackpak endp
-
- ; init variables for read...
- rrinit proc near
- mov pack.numpkt,0 ; Set the number of packets to zero
- mov pack.numrtr,0 ; Set the number of retries to zero
- mov pack.pktnum,0 ; Set the packet number to zero
- mov pack.numtry,0 ; Set the number of tries to zero
- mov filopn,0 ; say no file opened yet
- ret
- rrinit endp
-
- ; RECEIVE command -- Some code moved to the GET routine
-
- READ PROC NEAR
- mov flags.nmoflg,0 ; Override file name from other host
- ; mov bx,offset filhlp2 ; Text of help message
- mcmsgb filhlp2, cfilhlp2
-
- mov dx,offset locfil ; local file name string
- mov byte ptr locfil,0 ; clear it first
- mov ah,cmfile ; allow path names
- call comnd
- ret
- nop
- nop
- cmp ah,0 ; was an override filename given?
- je read0 ; e = no
- mov flags.nmoflg,1 ; yes, set flag = use this filename
- read0: mov ah,cmcfm ; Get a confirm
- call comnd
- ret
- nop
- nop
- mov pack.state,'R' ; Set the state to receive initiate
- mov flags.getflg,0 ; Reset flag (not a Get command)
- mov flags.xflg,0
- call serini ; initialize serial port
- jnc read0b ; nc = success
- or errlev,2 ; set DOS error level
- or fsta.xstatus,2 ; set status, failed
- or kstatus,2 ; global status
- test flags.remflg,dquiet ; quiet display mode?
- jnz read0a ; nz = yes. Don't write to screen
- mov ah,prstr
- ; mov dx,offset infms4 ; Failed message
- mcmsg infms4, cinfms4
-
- int dos
- read0a: ret ; return failure
- read0b: call rrinit ; init variables for read
- call init ; setup display form
- call ihostr ; initialize the host
-
- READ12: ; Called by GET & SRVSND, display ok
- mov kstatus,0 ; global status, success
- call begtim ; start next statistics group
- mov flags.cxzflg,0 ; Reset ^X/^Z flag
- mov ah,trans.chklen ; get desired checksum length
- mov curchk,ah ; and remember it here
- test flags.remflg,dquiet ; quiet display mode?
- jnz read2 ; nz = yes, no printing
- cmp flags.destflg,2 ; Receiving to the screen?
- je read21 ; e = yes, no formatted display
- call stpos
- mov ah,prstr ; Be informative
- ; mov dx,offset infms1
- mcmsg infms1, cinfms1
-
- int dos
- test flags.remflg,dserial ; serial display mode?
- jnz read2 ; nz = yes, skip initial retry display
- call rtpos ; Position cursor
- mov ax,pack.numrtr
- call nout ; Write the number of retries
-
- READ2: ; Called by GENERIC server command dispatcher
- cmp flags.xflg,1 ; Are we receiving to the screen?
- je read21 ; e = skip the screen stuff
- call nppos ; Position cursor for number of packets msg
- mov ax,pack.numpkt
- call nout ; Write the number of packets
- read21: mov ah,pack.state ; Get the state
- cmp ah,'D' ; Data receive state?
- jne read3
- call rdata ; yes, get data packets
- jmp read2
- read3: cmp ah,'F' ; File receive state?
- jne read4
- call rfile ; Call receive file
- jmp read2
- read4: cmp ah,'R' ; Receive initiate state?
- jne read5 ; ne = no
- call rinit
- jmp read2
- ; Receive Complete state processor
- read5: push ax ; save status in ah
- cmp flags.cxzflg,0 ; Completed or interrupted?
- je read5a ; e = ended normally
- or errlev,2 ; set DOS error level
- or fsta.xstatus,2+80h ; set status, failed + intervention
- or kstatus,2+80h ; global status
- read5a: push ax
- xor ax,ax ; tell statistics this is a receive operation
- call endtim ; stop file timer
- pop ax
- mov ah,curchk ; get working checksum
- mov trans.chklen,ah ; and restore for next file
- mov byte ptr locfil,0 ; clear local filename
- pop ax ; recover status in ah
- ; mov dx,offset infms3 ; Completed message
- mcmsg infms3, cinfms3
-
- cmp ah,'C' ; Receive complete state?
- je read6 ; e = yes, else receive failed
- or errlev,2 ; set DOS error level
- or fsta.xstatus,2 ; set status, failed
- or kstatus,2 ; global status
- ; mov dx,offset infms4 ; Failed message
- mcmsg infms4, cinfms4
-
- cmp filopn,2 ; file still open?
- jne read6 ; ne = no
- push dx
- call abort ; close file & maybe delete
- pop dx
- read6: cmp flags.xflg,0 ; Did we write to the screen?
- je read6a ; e = no, so print status
- cmp flags.destflg,2 ; Receiving to screen?
- je read6d ; Yes don't reset
- mov flags.xflg,0 ; Reset it
- jmp read6d ; Yes, so just return
- read6a: test flags.remflg,dquiet ; quiet display mode?
- jnz read6d ; nz = yes, keep going
- cmp flags.destflg,2 ; Receiving to the screen?
- je read6d ; e = yes, no formatted display
- push dx ; save message pointer
- call stpos ; Position cursor
- pop dx
- mov ah,prstr
- cmp flags.cxzflg,0 ; Completed or interrupted?
- je read6b ; Ended normally
- ; mov dx,offset infms6 ; Say was interrupted
- mcmsg infms6, cinfms6
-
- read6b: int dos
- cmp flags.belflg,0 ; Bell desired?
- je read6c ; No
- mov dx,offset ender ; Ring them bells
- int dos
- read6c: test flags.remflg,dserial ; serial display?
- jnz read6d ; nz = yes
- call clrmod ; clear Mode Line
- call rprpos ; Put prompt here
- read6d: jmp rskp
- READ ENDP
-
- ; Receive routines
-
- ; Receive init
- RINIT PROC NEAR
- mov ah,pack.numtry ; Get the number of tries
- cmp ah,imxtry ; Reached the maximum number of tries?
- jl rinit2
- ; mov dx,offset ermes7
- mcmsg ermes7, cermes7
- test flags.remflg,dquiet ; quiet display mode?
- jnz rinit1 ; nz = yes. Don't write to screen
- cmp flags.destflg,2 ; Receiving to the screen?
- je rinit1 ; e = yes, no formatted display
- call erpos ; Position cursor
- mov ah,prstr
- int dos ; Print an error message
- rinit1: mov bx,dx
- mov ah,trans.chklen
- mov curchk,ah ; Store checksum length we want to use
- mov trans.chklen,1 ; Send init checksum is always 1 char
- call errpack ; Send error packet just in case
- mov ah,curchk
- mov trans.chklen,ah ; Reset to desired value
- jmp abort ; Change the state to abort
- rinit2: inc ah ; Increment it
- mov pack.numtry,ah ; Save the updated number of tries
- mov ah,flags.getflg ; Get cmd? (holds get pkt type in ah)
- cmp ah,0 ; Have we already read in the packet?
- jne rin21a ; ne = yes, so don't call RPACK
- mov ah,dtrans.seol ; restore default end-of-line char
- mov trans.seol,ah
- mov ah,trans.chklen
- mov curchk,ah ; Save checksum length we want to use
- mov trans.chklen,1 ; Use 1 char for init packet
- call rpack ; Get a packet
- jmp rin22 ; Trashed packet: nak, retry
- call pktsize ; report packet size
- push ax
- mov ah,curchk
- mov trans.chklen,ah ; Reset to desired value
- pop ax
- cmp flags.cxzflg,0 ; does the user want out now?
- jne rinit4 ; ne = yes, quit
- rin21a: cmp ah,'S' ; Is it a send initiate packet?
- jne rinit3 ; If not see if its an error
- rin21: mov flags.getflg,0 ; Reset flag
- mov pack.numtry,0 ; Reset the number of tries
- mov ax,pack.seqnum ; Returned packet number. (Synchronize them.)
- inc ax ; Increment it
- and ax,3FH ; Turn off the two high order bits
- mov pack.pktnum,ax ; Save modulo 64 of the number
- inc pack.numpkt ; Increment the number of packets
- mov ax,pack.datlen ; Get the number of arguments received
- mov bx,offset data ; Get a pointer to the data
- call spar ; Get data into the proper variables
- mov bx,offset data ; Get a pointer to our data block
- call rpar ; Set up the receive parameters
- xchg ah,al
- mov ah,0
- mov pack.datlen,ax ; Store returned number of arguments
- mov ah,trans.chklen ; Checksum length we'll use
- mov curchk,ah ; Save it
- mov trans.chklen,1 ; Use 1 char for init packet
- call ackpak ; acknowledge the packet
- mov ah,curchk ; Checksum length we'll use
- mov trans.chklen,ah ; Reset to desired value
- mov pack.state,'F' ; Set the state to file send
- ret
- rin22: call nak0 ; nak the packet
- mov ah,curchk ; and only now change checksum from 1
- mov trans.chklen,ah ; Reset to desired value
- ret ; try again
-
- rinit3: cmp ah,'M' ; Message packet?
- jne rinit3e ; ne = no
- call dodec ; decode it
- call error1 ; display it
- ret
- rinit3e: cmp ah,'E' ; Is it an error packet?
- jne rinit4 ; ne = no
- call error ; yes
- rinit4: jmp abort
- RINIT ENDP
-
-
- ; Receive file
-
- RFILE PROC NEAR
- mov dl,maxtry
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl rfile1
- ; mov dx,offset ermes8
- mcmsg ermes8, cermes8
-
- jmp rcverr ; do error exit
- rfile1: inc pack.numtry ; Save the updated number of tries
- call rpack ; Get a packet
- jmp nak0 ; Trashed packet: nak, retry
- call pktsize ; report packet size
- cmp ah,'S' ; Is it a send initiate packet?
- je rfil10
- cmp ah,'I' ; An Initialization packet?
- je rfil10 ; e = yes, don't decode it
- call dodec ; Decode all other incoming packets
- jmp rfile2 ; No, try next type
- rfil10: mov dl,imxtry ; S and I packets
- cmp pack.numtry,dl ; Reached the maximum number of tries?
- jl rfil12 ; If not proceed
- ; mov dx,offset ermes7
- mcmsg ermes7, cermes7
-
- jmp rcverr ; do error exit
- rfil12: mov ax,pack.pktnum ; Get the present packet number
- dec ax ; Decrement
- and ax,3fh ; do module 64
- cmp ax,pack.seqnum ; Is the packet's number one less than now?
- je rfil13
- jmp nak0 ; No, NAK and try again
- rfil13: mov pack.numtry,0 ; Reset the number of tries
- mov bx,offset data ; Get a pointer to our data block
- call rpar ; Set up the parameter information
- xchg ah,al
- mov ah,0
- mov pack.datlen,ax ; Save the number of arguments
- jmp ackpak ; acknowledge the packet
-
- rfile2: cmp ah,'Z' ; Is it an EOF packet?
- jne rfile3 ; No, try next type
- mov dl,maxtry ; Z packets
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl rfil21 ; If not proceed
- ; mov dx,offset ermes9
- mcmsg ermes9, cermes9
-
- jmp rcverr ; do error exit
- rfil21: mov ax,pack.pktnum ; Get the present packet number
- dec ax ; Decrement
- and ax,3fh ; do modulo 64
- cmp ax,pack.seqnum ; Is the packet's number one less than now?
- je rfil24
- jmp nak0 ; No, NAK and try again
- rfil24: mov pack.numtry,0
- mov pack.datlen,0 ; No data. (The packet number is in seqnum.)
- jmp ackpak ; acknowledge the packet
-
- rfile3: cmp ah,'F' ; Start of file (F or X packet)?
- je rfil31 ; e = yes
- cmp ah,'X' ; Text header packet?
- jne rfile4 ; Neither one.
- mov flags.xflg,1 ; 'X', say receiving to the screen
- rfil31: mov ax,pack.seqnum ; Get the packet number
- cmp ax,pack.pktnum ; Is it the right packet number?
- je rfil32
- jmp nak1 ; No, NAK it and try again
- rfil32: inc ax ; Increment the packet number
- and ax,3FH ; Turn off the two high order bits
- mov pack.pktnum,ax ; Save modulo 64 of the number
- inc pack.numpkt ; Increment the number of packets
- mov filopn,0 ; assume not writing to a disk file
- call dodec ; Decode incoming packet for filename
- call gofil ; Get a file to write to
- jmp abort
- mov chrcnt,maxpack ; reset output buffer to be empty
- cmp flags.xflg,0 ; writing to a disk file?
- jne rfil32a ; ne = no
- mov filopn,2 ; Disk file open for writing
- rfil32a:
- test flags.remflg,dserial ; serial display mode?
- jz rfil33 ; z = no
- mov ah,prstr
- mov dx,offset crlf ; display cr/lf
- int dos
- rfil33:
- mov pack.state,'D' ; Set the state to data receive
- mov pack.numtry,0 ; Reset the number of tries
- mov pack.datlen,0 ; No data. (The packet number is in seqnum.)
- jmp ackpak ; acknowledge the packet
-
- rfile4: cmp ah,'B' ; End of transmission?
- jne rfile5 ; ne = no
- mov ax,pack.pktnum
- cmp ax,pack.seqnum ; Do we match?
- je rfil41
- jmp nak1 ; No, NAK it and try again
- rfil41: mov pack.state,'C' ; Set the state to complete
- mov pack.datlen,0 ; No data. (Packet number already in seqnum)
- jmp ackpak ; acknowledge the packet
-
- rfile5: cmp ah,'M' ; Message packet?
- jne rfile5e ; ne = no
- call dodec ; decode it
- jmp error1 ; display it and return
-
- rfile5e:cmp ah,'E' ; Is it an error packet?
- jne rfile6 ; ne = no
- call error
- rfile6: jmp abort
- RFILE ENDP
-
- ; Get file attributes from packet
- ; Recognize file size in bytes and kilobytes (used if bytes missing),
- ; file time and date. Reject Mail commands. Return carry clear for success,
- ; carry set for failure. If rejecting place reason code in byte temp.
- GETATT PROC NEAR
- mov bx,offset data ; pointer
- getat0: push bx
- sub bx,offset data
- cmp bx,pack.datlen ; are we beyond end of data?
- pop bx
- jl getat1 ; l = not yet
- clc
- ret ; has carry clear for success
-
- getat1: cmp byte ptr [bx],'1' ; byte length field?
- jne getat2 ; ne = no
- mov al,[bx] ; remember attribute
- mov attrib,al
- inc bx ; pointer
- call getas ; get file size
- call spchk ; check available disk space
- jnc getat0
- ret ; return failure
-
- getat2: cmp byte ptr [bx],'!' ; kilobyte length field?
- jne getat3 ; ne = no
- mov al,[bx] ; remember attribute
- mov attrib,al
- inc bx ; pointer
- call getak ; get file size
- jc getat5;;;2a ; carry means decode rejected
- call spchk ; check available disk space
- jnc short getat0
- getat2a:ret ; return failure
-
- getat3: cmp byte ptr [bx],'#' ; date field?
- jne getat4 ; ne = no
- mov al,[bx] ; remember attribute
- mov attrib,al
- inc bx
- call getatd ; get file date
- jmp short getat0
-
- getat4: cmp byte ptr [bx],'+' ; Disposition?
- jne getat5 ; ne = no
- mov al,[bx] ; remember attribute
- mov attrib,al
- cmp byte ptr [bx+2],'M' ; Mail indicator
- jne getat5 ; ne = no, ignore field
- stc ; set carry for failure
- ret
-
- getat5: inc bx ; look at length field
- mov al,[bx]
- sub al,' ' ; remove ascii bias
- mov ah,0
- inc ax ; include length field byte
- add bx,ax ; skip to next attribute
- jmp getat0
- ; Decode File length (Byte) field
- getas: mov cl,[bx] ; length of file size field
- inc bx ; point at file size data
- sub cl,' ' ; remove ascii bias
- mov ch,0
- mov ax,0 ; current length, bytes
- mov dx,0
- getas2: push cx
- shl dx,1 ; high word of size, times two
- mov di,dx ; save
- shl dx,1
- shl dx,1 ; times 8
- add dx,di ; yields dx * 10
- mov di,dx ; save dx
- mov dx,0
- mov cx,10 ; also clears ch
- mul cx ; scale up previous result in ax
- mov cl,[bx] ; get a digit
- inc bx
- sub cl,'0' ; remove ascii bias
- add ax,cx ; add to current length
- adc dx,0 ; extend result to dx
- add dx,di ; plus old high part
- pop cx
- loop getas2
- mov ofilsz+2,ax ; low order word
- mov ofilsz,dx ; high order word
- ret
- ; Decode Kilobyte attribute
- getak: mov ax,ofilsz+2 ; current filesize, low word
- add ax,ofilsz
- cmp ax,0 ; zero if not used yet
- je getak1 ; e = not used before
- dec bx ; backup pointer
- stc ; set carry to ignore this field
- ret
- getak1: call getas ; parse as if Byte field
- mov ax,ofilsz+2 ; get low word of size
- mov dx,ofilsz ; high word
- mov dh,dl ; times 256
- mov dl,ah
- mov ah,al
- mov al,0
- shl dx,1 ; times four to make times 1024
- shl dx,1
- rol ax,1 ; two high bits of ah to al
- rol ax,1
- and al,3 ; keep them
- or dl,al ; insert into high word
- mov al,0
- mov ofilsz,dx ; store high word
- mov ofilsz+2,ax ; store low word
- clc ; clear carry
- ret
-
- getatd: ; File date and time
- mov word ptr ftime,1 ; two seconds past midnight
- mov word ptr fdate,0
- mov dl,[bx] ; field length
- mov dh,0
- sub dl,' ' ; remove ascii bias
- inc bx ; next field
- add dx,bx ; where next field begins
- mov temp,dx ; save in temp
- mov ax,0 ; recover file date and time
- mov dh,10 ; multiplier
- cmp byte ptr[bx+6],' ' ; short form date (yymmdd)?
- je getad2 ; e = yes
- add bx,2 ; skip century digits (19)
- getad2: mov ax,10
- mov dx,[bx] ; get year tens and units digits
- add bx,2 ; dl has tens, dh has units
- sub dx,'00' ; remove ascii bias
- mul dl ; ax = high digit times ten
- add al,dh ; units digit
- sub ax,80 ; remove rest of 1980 bias
- jns getad2a ; ns = no sign = non-negative result
- mov ax,0 ; don't store less than 1980
- getad2a:shl al,1 ; adjust for DOS bit format
- mov fdate+1,al
- mov ax,[bx] ; get month digits
- add bx,2
- sub ax,'00' ; remove ascii bias
- cmp al,0 ; tens digit set?
- je getad2b ; e = no
- add ah,10 ; add to units digit
- getad2b:cmp ah,8 ; high bit of month set?
- jb getad3 ; b = no
- or fdate+1,1
- sub ah,8 ; and deduct it here
- getad3: mov cl,5
- shl ah,cl ; normalize months bits
- mov fdate,ah
- mov dx,[bx] ; do day of the month
- add bx,2 ; dh has units, dl has tens digit
- sub dx,'00' ; remove ascii bias
- mov ax,10
- mul dl ; ax = ten times tens digit
- add al,dh ; plus units digit
- or fdate,al
- cmp bx,temp ; are we at the end of this field?
- jae getad5 ; ae = yes, prematurely
- inc bx ; skip space separator
- getad4: mov ax,10 ; prepare for hours
- mov dx,[bx] ; hh digits
- add bx,2
- sub dx,'00' ; remove ascii bias
- mul dl ; 10*high digit of hours
- add al,dh ; plus low digit of hours
- mov cl,3 ; normalize bits
- shl al,cl
- mov ftime+1,al ; store hours
- inc bx ; skip colon
- mov ax,10 ; prepare for minutes
- mov dx,[bx] ; mm digits
- add bx,2
- sub dx,'00' ; remove ascii bias
- mul dl ; 10*high digit of minutes
- add al,dh ; plus low digit of minutes
- mov ah,0
- mov cl,5 ; normalize bits
- shl ax,cl
- or ftime+1,ah ; high part of minutes
- mov ftime,al ; low part of minutes
- cmp bx,temp ; are we at the end of this field
- jae getad5 ; ae = yes, quit here
- inc bx ; skip colon
- mov ax,10 ; prepare for seconds
- mov dx,[bx] ; ss digits
- add bx,2
- sub dx,'00' ; remove ascii bias
- mul dl ; 10*high digit of seconds
- add al,dh ; plus low digit of seconds
- shr al,1 ; store as double-seconds for DOS
- or ftime,al ; store seconds
- getad5: ret
- GETATT ENDP
-
- ; Receive data
-
- RDATA PROC NEAR
- mov dl,maxtry
- cmp pack.numtry,dl ; Get the number of tries
- jl rdata1
- ; mov dx,offset erms10
- mcmsg erms10, cerms10
-
- jmp rcverr ; do error exit
- rdata1: inc pack.numtry ; Save the updated number of tries
- call rpack ; Get a packet
- jmp nak0 ; Trashed packet: nak, retry
- nop
- call pktsize ; report packet size
- cmp ah,'D' ; Is it a data packet?
- je rdat11 ; e = yes
- cmp ah,'A' ; Attributes packet?
- jne rdata7 ; ne = no
- mov ax,pack.pktnum
- cmp ax,pack.seqnum ; Do we match?
- je rdata6
- jmp nak1 ; No, NAK it and try again
- rdata6: call getatt ; get file attributes from packet
- mov pack.numtry,0 ; Reset number of tries
- jnc rdata6a ; nc = success
- mov pack.datlen,2 ; 2 bytes (Packet number already in seqnum)
- mov data,'N' ; Decline the transfer
- mov al,attrib ; get attribute causing rejection
- mov data+1,al ; report rejection reason to sender
- or fsta.xstatus,2 ; set status, failed
- mov kstatus,2 ; global status
- jmp short rdata6b
- rdata6a:mov pack.datlen,0 ; No data. (Packet number already in seqnum)
- rdata6b:mov ax,pack.pktnum
- inc ax ; Increment the packet number
- and ax,3FH ; Turn off the two high order bits
- mov pack.pktnum,ax ; Save modulo 64 of the number
- inc pack.numpkt ; Increment the number of packets
- jmp ackpak ; acknowledge the packet
-
- rdata7: call dodec ; Decode data
- jmp rdata2 ; try next type
- ; D packets
- rdat11: mov ax,pack.pktnum ; Get the present packet number
- cmp ax,pack.seqnum ; Is the packet's number correct?
- jz rdat14
- mov dl,maxtry
- cmp pack.numtry,dl ; Have we reached the maximum number of tries?
- jl rdat12 ; If not proceed
- ; mov dx,offset erms10
- mcmsg erms10, cerms10
-
- jmp rcverr ; do error exit
- rdat12: mov ax,pack.pktnum
- dec ax
- and ax,3fh ; do modulo 64
- cmp ax,pack.seqnum ; Is the packet's number one less than now?
- je rdat13
- jmp nak0 ; No, NAK it and try again
- rdat13: mov pack.numtry,0 ; Reset number of tries
- mov pack.datlen,0 ; No data. (The packet number is in seqnum.)
- jmp ackpak ; acknowledge the packet
-
- rdat14: inc pack.pktnum ; Increment the packet number
- and pack.pktnum,3fh ; Save modulo 64 of the number
- inc pack.numpkt ; Increment the number of packets
- mov ax,pack.datlen ; Get the length of the data
- cmp flags.cxzflg,0 ; Has the user typed a ^X or ^Z?
- je rdt14x ; No, write out the data
- or fsta.xstatus,2+80h ; set status, failed + intervention
- mov kstatus,2+80h ; global status
- cmp flags.abfflg,1 ; Discard incomplete files?
- je rdat15 ; If yes don't write data out to file
- rdt14x: call ptchr ; decode the data and output to file
- jmp abort ; Unable to write out chars; abort
- rdat15: mov pack.numtry,0 ; Reset the number of tries
- mov pack.datlen,0 ; No data. (Packet number still in seqnum.)
- cmp flags.cxzflg,0 ; Interrupt file transfer?
- je rdat16 ; Nope
- or fsta.xstatus,2+80h ; set status, failed + intervention
- mov kstatus,2+80h ; global status
- mov bx,offset data ; Send data in ACK in case remote
- mov ah,flags.cxzflg ; knows about ^X/^Z
- mov [bx],ah ; Put data into the packet
- mov pack.datlen,1 ; Set data size to 1
- mov cx,1
- call doenc
- rdat16: jmp ackpak ; acknowledge the packet
-
- rdata2: cmp ah,'F' ; Start of file?
- je rdat20 ; e = yes
- cmp ah,'X' ; Text header packet?
- jne rdata3 ; No, try next type
- rdat20: mov dl,maxtry ; F or X packet
- cmp pack.numtry,dl ; Reached the max number of tries?
- jl rdat21 ; If not proceed
- ; mov dx,offset ermes8
- mcmsg ermes8, cermes8
-
- jmp rcverr ; do error exit
- rdat21: mov ax,pack.pktnum
- dec ax
- and ax,3fh ; modulo 64
- cmp ax,pack.seqnum ; Is the packet's number one less than now?
- je rdat22
- jmp nak0 ; No, NAK it and try again
- rdat22: mov pack.numtry,0 ; Reset number of tries
- mov pack.datlen,0 ; No data. (The packet number is in seqnum.)
- jmp ackpak ; acknowledge the packet
-
- rdata3: cmp ah,'Z' ; Is it a EOF packet?
- je rdat3x ; e = yes
- jmp rdata4 ; Try and see if its an error
- rdat3x: mov ax,pack.pktnum ; Get the present packet number
- cmp ax,pack.seqnum ; Is the packet's number correct?
- je rdat32
- jmp nak0 ; No, NAK it and try again
- rdat32: inc ax ; Increment the packet number
- and ax,3FH ; Turn off the two high order bits
- mov pack.pktnum,ax ; Save modulo 64 of the number
- inc pack.numpkt
- call dodec ; Decode incoming packet
- cmp flags.cxzflg,0 ; Do we want to discard the file?
- jne rdt32x ; ne = yes
- cmp fmtdsp,0 ; formatted screen?
- je rdat32a ; e = no, no message
- mov ax,ofilsz ; high word of attributes file size
- or ax,ofilsz+2 ; low word
- cmp ax,0 ; was file size given by other side?
- je rdat32a ; e = no
- call perpos ; position cursor to percent done
- mov dx,offset donemsg ; say 100%
- mov ah,prstr
- int dos
- rdat32a:cmp pack.datlen,1 ; One piece of data?
- jne rdat33 ; Nope - finish writing out file?
- cmp data,'D' ; is the data "D" for discard?
- jne rdat33 ; Nope - write out file
- rdt32x: cmp flags.abfflg,0 ; Keep incomplete files?
- je rdat33 ; Yes, go write it out
- cmp flags.xflg,1 ; Writing to the screen?
- je rdt32y ; Don't close "file"
- cmp flags.destflg,2 ; file destination = screen?
- je rdt32y ; e = yes, no file to close
- push bx
- mov ah,close2 ; DOS 2.0 file close
- mov bx,diskio.handle ; file handle
- int dos ; Kill it, ignore errors
- pop bx
- mov filopn,0 ; File closed now
- mov dx,offset diskio.string ; get the filename
- mov ah,del2 ; DOS 2.0 file delete
- int dos
- rdt32y: cmp flags.cxzflg,'X' ; Kill one file or all?
- je rdt32ya ; e = one (^X)
- jmp rdat36 ; No so leave flag alone
- rdt32ya:call cxmsg ; Clear msg about interrupt
- or errlev,2 ; set DOS error level
- or fsta.xstatus,2+80h ; set status, failed + intervention
- mov kstatus,2+80h ; global status
- test flags.remflg,dquiet ; quiet display?
- jnz rdt32z ; nz = yes
- cmp flags.destflg,2 ; Receiving to the screen?
- je rdt32z ; e = yes, no formatted display
- call intmsg
- rdt32z: mov flags.cxzflg,0 ; Reset - ^X only kills one file
- jmp rdat36
- rdat33: cmp flags.eofcz,0 ; should we write a ^Z?
- jz rdat35 ; no, keep going
- cmp flags.xflg,0 ; writing to a file?
- jne rdat35 ; no, skip ^Z
- rdt33x: cmp chrcnt,0 ; any space left in output buffer?
- jg rdat34 ; g = yes
- call outbuf ; Write out buffer if no room for ^Z
- jmp abort
- rdat34: mov cl,'Z'- 40h ; Put in a ^Z for EOF
- push bx
- mov bx,bufpnt ; Get the dma pointer
- mov [bx],cl ; Add it
- pop bx
- dec chrcnt
- rdat35: call outbuf ; Output the last buffer
- jmp abort ; Give up if the disk is full
- cmp flags.xflg,1 ; Writing to the screen?
- je rdat37 ; Yes, don't close "file"
- cmp flags.destflg,2 ; file destination = screen?
- je rdat37 ; e = yes, no file to close
- push bx ; do file attributes and close
- mov cx,word ptr ftime ; new time
- mov dx,word ptr fdate ; new date
- mov word ptr fdate,0
- mov word ptr ftime,0 ; clear current time/date attributes
- mov ax,cx
- or ax,dx
- jz rdat35b ; z = no attributes to set
- cmp cx,0 ; time set as null?
- jne rdat35a ; ne = no
- inc cl ; two seconds past midnight
- rdat35a:mov ah,setattr ; set file date/time attributes
- mov al,1 ; set, not get
- mov bx,diskio.handle ; file handle
- int dos ; end of file attributes
- rdat35b:mov ah,close2 ; DOS 2.0 file close
- mov bx,diskio.handle ; file handle
- int dos
- pop bx
- mov filopn,0 ; File closed now
- rdat36: cmp flags.destflg,0 ; Writing to printer?
- jne rdat37 ; ne = no, skip next part
- cmp flags.xflg,1 ; Writing to screen?
- je rdat37 ; Yes, skip this part
- mov dl,ff ; Send a form feed
- mov ah,lstout ; Write out to first printer
- int dos
- rdat37: mov pack.numtry,0 ; Reset the number of tries
- mov pack.datlen,0 ; No data. (The packet number is in seqnum.)
- call ackpak ; acknowledge the packet
- mov pack.state,'F'
- mov ax,0 ; tell statistics this was a receive operation
- call endtim ; get tod & size of file transfer
- ret
- rdata4: cmp ah,'M' ; Message packet?
- jne rdata4e ; ne = no
- call dodec ; decode it
- jmp error1 ; display it and return
-
- rdata4e: cmp ah,'E' ; Is it an error packet?
- jne rdata5 ; ne = no
- call error
- rdata5: jmp abort
- RDATA ENDP
-
- ; Error exit. Enter with dx pointing to error message. [jrd]
- rcverr proc near
- test flags.remflg,dquiet ; quiet display mode?
- jnz rcver1 ; nz = yes. Don't write to screen
- cmp flags.destflg,2 ; Receiving to the screen?
- je rcver1 ; e = yes, no formatted display
- call erpos ; Position cursor
- mov ah,prstr
- int dos ; Print an error message
- rcver1: mov bx,dx ; set bx to error message
- call errpack ; Send error packet just in case
- jmp abort ; Change the state to abort
- rcverr endp
-
- ; Called by GETATT in receiver code to verify sufficient disk space.
- ; Gets file path from diskio.string setup in mssfil, remote size in ofilsz
- ; from getatt, and whether a disk file or not via ioctl on the file handle.
- ; Returns carry clear if enough space.
- spchk proc near ; check for enough disk space
- push ax
- push bx
- push cx
- push dx
- mov ah,ioctl ; ask DOS about this file handle
- mov al,0 ; get info
- mov bx,diskio.handle
- int dos
- test dl,80h ; handle is a disk file?
- jnz spchk5b ; nz = no, always enough space
- inc dl
- and dl,01fh ; get current drive from bits 5-0
- mov ah,36h ; get disk free space
- int dos
- cmp ax,0ffffh ; error response?
- je spchk6 ; e = yes
- mul bx ; sectors/cluster * clusters = sectors
- mov bx,dx ; save high word of sectors (> 64K)
- mul cx ; bytes = sectors * bytes/sector
- push ax ; save low word of bytes
- mov ax,bx ; recall sectors high word
- mov bx,dx ; save current bytes high word
- mul cx ; high word sectors * bytes/sector
- add ax,bx ; new high bytes + old high bytes
- push ax ; save high word, dx:ax
- mov dx,ofilsz ; high word of file size dx:ax
- mov ax,ofilsz+2 ; low word
- mov cx,dx ; copy size long word to cx:bx
- mov bx,ax
- shr bx,1 ; divide long word by two
- shr cx,1
- jnc spchk2 ; nc = no carry down
- or bx,8000h ; get carry down
- spchk2: shr bx,1 ; divide by two again
- shr cx,1
- jnc spchk3
- or bx,8000h ; get carry down
- spchk3: shr bx,1 ; divide long word by two
- shr cx,1
- jnc spchk4 ; nc = no carry down
- or bx,8000h ; get carry down
- spchk4: shr bx,1 ; divide long word by two
- shr cx,1
- jnc spchk5 ; nc = no carry down
- or bx,8000h ; get carry down
- spchk5: add ax,bx ; form dx:ax = (17/16) * dx:ax
- adc dx,cx
- spchk5a:pop cx ; high word of disk space
- pop bx ; low word
- sub bx,ax ; minus inflated file size, low word
- sbb cx,dx ; and high word
- js spchk6 ; s = not enough space for file
- spchk5b:clc
- jmp short spchk7 ; enough space
- spchk6: call erpos ; Position cursor
- mov ah,prstr
- ; mov dx,offset erms11 ; Not enough space for file
- mcmsg erms11, cerms11
-
- int dos
- stc
- spchk7: pop dx
- pop cx
- pop bx
- pop ax
- ret
- spchk endp
-
-
- ; Jumping to this location is like retskp. It assumes the instruction
- ; after the call is a jmp addr
-
- RSKP PROC NEAR
- pop bp
- add bp,3
- push bp
- ret
- RSKP ENDP
-
- code ends
- end
-